package com.oig.sys.base.service.impl;

import com.oig.common.constants.CommonEnum;
import com.oig.common.exception.BadRequestException;
import com.oig.sys.base.constants.SysBaseConstants;
import com.oig.sys.base.dao.ITbParamDao;
import com.oig.sys.base.dto.ParamDto;
import com.oig.sys.base.entity.TbParam;
import com.oig.sys.base.service.ITbParamService;
import com.oig.sys.base.vo.ParamVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author wuxl
 */
@Slf4j
@Service
public class TbParamServiceImpl implements ITbParamService {

	private final ITbParamDao tbParamDao;
	private final RedisTemplate<String, Object> redisTemplate;

	@Autowired
	public TbParamServiceImpl( ITbParamDao tbParamDao, RedisTemplate<String, Object> redisTemplate){
		 this.tbParamDao = tbParamDao;
		 this.redisTemplate = redisTemplate;
	}

	@Transactional
	@Override
	public ParamVo addTbParam(ParamDto paramDto) {
		TbParam param = this.tbParamDao.getByCode(paramDto.getCode()) ;
		if (param!=null){
			throw new BadRequestException("编码重复") ;
		}
		param = new TbParam();
		BeanUtils.copyProperties(paramDto, param);
		param.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbParamDao.save(param);
		ParamVo paramVo = new ParamVo();
		BeanUtils.copyProperties(param, paramVo);
		return paramVo;
	}

	@Transactional
	@Override
	public ParamVo updateTbParam(ParamDto paramDto) {
		TbParam param = this.tbParamDao.getByCode(paramDto.getCode()) ;
		if (param==null){
			throw new BadRequestException("记录不存在") ;
		}
		BeanUtils.copyProperties(paramDto, param, "code");
		this.tbParamDao.save(param);
		ParamVo paramVo = new ParamVo();
		BeanUtils.copyProperties(param, paramVo);
		return paramVo;
	}

	@Transactional
	@Override
	public void cancelTbParam(String code) {
		TbParam param = this.tbParamDao.getByCode(code) ;
		if (param==null){
			throw new BadRequestException("记录不存在") ;
		}
		param.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		this.tbParamDao.save(param) ;
	}


	@Override
	public ParamVo getParam(String code) {
		return this.tbParamDao.findVoByCode(code);
	}


	private String addIdStepNum(String code){
		TbParam param = tbParamDao.getByCode(code) ;
		if (param==null){
			throw new BadRequestException("系统参数："+code+" 不存在") ;
		}
		if (!SysBaseConstants.DEF_INDEX_TYPE.equals(param.getType())){
			throw new BadRequestException("系统参数："+code+" 不是id生成器序号") ;
		}
		if (CommonEnum.FlagEnum.FALSE_FLAG.getCode().equals(param.getCacheFlag())){
			throw new BadRequestException("系统参数："+code+" 未设置缓存") ;
		}
		String value = param.getValue();
		//将数据库value增加2000
		param.setValue(String.valueOf(Integer.parseInt(value)+SysBaseConstants.ID_INDEX_SIZE));
		this.tbParamDao.save(param);
		return value;
	}

	@Transactional
	@Override
	public Integer getNextId(String code) {
		String key = SysBaseConstants.REDIS_KEY_PARAM+code;
		if (Boolean.FALSE.equals(redisTemplate.hasKey(key))){		//如果缓存没有，这加入缓存里去
			//throw new BadRequestException("系统参数："+code+" 未缓存") ;
			String value = this.addIdStepNum(code);
			int indexNum = Integer.parseInt(value);
			log.info("add id cache:{}",indexNum);
			redisTemplate.opsForValue().set(key, indexNum);
		}
		//缓存里有的
		Long idIndex = redisTemplate.opsForValue().increment(key);
		if (idIndex==null){
			throw new BadRequestException("系统参数："+code+" 缓存值非数值") ;
		}
		//当前缓存余数，到了2000了，就从新取2000
		int num = idIndex.intValue() % SysBaseConstants.ID_INDEX_SIZE + 1 ;
		if (SysBaseConstants.ID_INDEX_SIZE==num){
			String value = this.addIdStepNum(code);
			log.info("add id Step:{}",value);
		}
		return idIndex.intValue();
	}

	@Transactional
	@Override
	public void resetAllIdIndex() {
		List<TbParam> paramList = this.tbParamDao.findAllIdIndex();
		for (TbParam param : paramList){
			log.info("reset param:{}", param);
			param.setValue(String.valueOf(SysBaseConstants.ID_INDEX_SIZE));
			this.tbParamDao.save(param);
			redisTemplate.opsForValue().set(SysBaseConstants.REDIS_KEY_PARAM+param.getCode(), 0);
		}
	}


}
